package com.richest.api.controller.pay;

import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.richest.api.controller.form.UnifiedOrderForm;
import com.richest.api.utils.GlobalNames;
import com.richest.api.utils.RequestHandler;
import com.richest.api.utils.TenpayUtil;
import com.richest.api.utils.WXAppInfo;
import com.richest.api.utils.WXConfigUtil;
import com.richest.api.utils.WxMD5Util;

/**
 * 微信支付业务逻辑
 * 
 * @author 赵鸿超 2017年9月24日
 */
public class WxPay {
	private static Logger logger = LoggerFactory.getLogger(WxPay.class);
	public static final String TRADE_TYPE_PUB = "APP"; // 交易类型:公众号支付
	public static final String SIGN_TYPE = "MD5"; // 签名方式
	public static final String WECHAT_PAY = "WeChat"; // 微信支付平台

	@Autowired

	/**
	 * 生成微信公众号支付商户订单
	 * 
	 * @author 赵鸿超 2017年9月24日
	 * @param strBody
	 *            商品详情
	 * @param attach
	 *            会员ID
	 * @param strTotalFee
	 *            总金额
	 * @param strSpbillCreateIp
	 *            终端IP
	 * @param strOpenId
	 *            用户标识
	 * @return String JSON字符串
	 * @throws Exception
	 */
	public Map<String, String> wxUnifiedOrder(UnifiedOrderForm form) throws Exception {
		WxMD5Util md5Util = new WxMD5Util();
		Map<String, String> returnMap = new HashMap<>();
		WXConfigUtil config = new WXConfigUtil();
		WXPay wxpay = new WXPay(config);
		Map<String, String> data = new HashMap<>();

		data.put("appid", config.getAppID());
		data.put("mch_id", config.getMchID());
		data.put("nonce_str", WXPayUtil.generateNonceStr());
		String body = "订单支付";
		data.put("body", body);
		data.put("out_trade_no", form.getOut_trade_no());
		data.put("total_fee", form.getTotal_fee());
		// 自己的服务器IP地址
		data.put("spbill_create_ip", form.getSpbill_create_ip());
		// 异步通知地址（请注意必须是外网）
		data.put("notify_url", WXAppInfo.getNotifyUrl());
		// 交易类型
		data.put("trade_type", TRADE_TYPE_PUB);
		// 附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
		data.put("attach", form.getAttach());
		String sign1 = md5Util.getSign(data);
		data.put("sign", sign1);

		try {
			// 使用官方API请求预付订单
			Map<String, String> response = wxpay.unifiedOrder(data);
			logger.debug(JSON.toJSONString(response));
			String returnCode = response.get("return_code"); // 获取返回码
			// 若返回码为SUCCESS，则会返回一个result_code,再对该result_code进行判断
			if (returnCode.equals("SUCCESS")) {// 主要返回以下5个参数
				returnMap.put("appid", response.get("appid"));
				returnMap.put("partnerid", response.get("mch_id"));
				returnMap.put("prepayid", response.get("prepay_id"));
				returnMap.put("package", "Sign=WXPay");
				returnMap.put("noncestr", response.get("nonce_str"));
				returnMap.put("timestamp", TenpayUtil.getUnixTime());// 单位为秒
				// 这里不要使用请求预支付订单时返回的签名,二次签名
				returnMap.put("sign", md5Util.getSign(returnMap));
				returnMap.put("extdata", form.getAttach());
				return returnMap;
			} else {
				return returnMap;
			}
		} catch (Exception e) {
			System.out.println(e);
			// 系统等其他错误的时候
		}
		return returnMap;
	}

	/**
	 * 验证微信签名
	 * 
	 * @author 赵鸿超 2017年9月24日
	 * @param mapParams
	 *            微信回调参数Map集合
	 * @return String JSON字符串
	 * @throws Exception
	 */
	public String verifyWeChatSign(SortedMap<String, String> mapParams) throws Exception {
		/**
		 * 获取福气快线公众号配置信息
		 */
		String strServiceApiKey = WXAppInfo.getServiceApiKey(); // 微信支付服务商的API密钥
		String strCommonApiKey = WXAppInfo.getCommonApiKey(); // 微信支付普通商户的API密钥

		/**
		 * 解析出sub_mch_id变量值，即子商户号。判断子商户号是否为空
		 */
		String strSign = ""; // 签名
		String sub_mch_id = mapParams.get("sub_mch_id"); // 子商户号
		// 如果为空，表示这笔交易是以普通商户模式进行，则用普通商户的API密钥计算签名
		if (sub_mch_id == null || "".equals(sub_mch_id)) {
			strSign = RequestHandler.createSign(mapParams, strCommonApiKey);
		}
		// 如果不为空，表示这笔交易以福气快线服务商模式进行,则用福气快线服务商的API密钥计算签名
		else {
			strSign = RequestHandler.createSign(mapParams, strServiceApiKey);
		}
		logger.info("生成签名 ：" + strSign);

		/**
		 * 解析出传入的sign变量值，与生成的签名比较，输出验证结果
		 */
		String strParaSign = mapParams.get("sign"); // 接口传入的签名
		logger.info("传入签名：" + strParaSign);
		String strVerifyRet = ""; // 签名验证结果
		if (strSign.equals(strParaSign)) {
			strVerifyRet = "0"; // 验证成功
		} else {
			strVerifyRet = "1"; // 验证失败
		}

		/**
		 * 组织输出结果JSON串
		 */
		Map<String, Object> resultMap = new HashMap<String, Object>(); // 输出结果集合
		resultMap.put("result", GlobalNames.CALL_RESULT_SUCC);
		resultMap.put("errmessage", "");
		resultMap.put("strVerifyRet", strVerifyRet);
		return JSON.toJSONString(resultMap);
	}
}
